#include <main.h>

unsigned int onesec;
unsigned onesec_flag=0;
unsigned int secs=0;
unsigned int secs_2=30;
unsigned int secs_3=20;

#INT_TIMER2
void TIMER2_isr(void)
{
	onesec++;
	if(onesec==20) {onesec=0;onesec_flag=1;}
}

unsigned long i = 0 ; // Start countdown from 40

unsigned int seg(unsigned int num) {
    switch (num) {
        case 0: return 0x3F;
        case 1: return 0x06;
        case 2: return 0x5B;
        case 3: return 0x4F;
        case 4: return 0x66;
        case 5: return 0x6D;
        case 6: return 0x7D;
        case 7: return 0x07;
        case 8: return 0x7F;
        case 9: return 0x6F;
        default: return 0x00; // Invalid input
    }
}

void update_display(unsigned int number) {
    unsigned int digit;

    // Update the ones place on PORTC
    digit = number % 10;
    output_b(seg(digit)); // Send segment data to PORTC
    delay_ms(2);

    // Update the tens place on PORTB
    digit = (number / 10) % 10;
    output_j(seg(digit)); // Send segment data to PORTB
    delay_ms(2);
}

void update_display_2(unsigned int number_2) {
    unsigned int digit_2;

    // Update the ones place on PORTC
    digit_2 = number_2 % 10;
    output_d(seg(digit_2)); // Send segment data to PORTC
    delay_ms(2);

    // Update the tens place on PORTB
    digit_2 = (number_2 / 10) % 10;
    output_c(seg(digit_2)); // Send segment data to PORTB
    delay_ms(2);
}

void update_display_3(unsigned int number_3) {
    unsigned int digit_3;

    // Update the ones place on PORTC
    digit_3 = number_3 % 10;
    output_f(seg(digit_3)); // Send segment data to PORTC
    delay_ms(2);

    // Update the tens place on PORTB
    digit_3 = (number_3 / 10) % 10;
    output_e(seg(digit_3)); // Send segment data to PORTB
    delay_ms(2);
}



void set_lights(unsigned int H, unsigned int A, unsigned int G)
{
	if (H == 0) H = 0b001; // Default red for H
    if (A == 0) A = 0b001; // Default red for A
    if (G == 0) G = 0b001; // Default red for G

    output_bit(pin_H2, (H >> 2) & 1);
    output_bit(pin_H1, (H >> 1) & 1);
    output_bit(pin_H0, (H >> 0) & 1);

    output_bit(pin_A2, (A >> 2) & 1);
    output_bit(pin_A1, (A >> 1) & 1);
    output_bit(pin_A0, (A >> 0) & 1);

    output_bit(pin_G2, (G >> 2) & 1);
    output_bit(pin_G1, (G >> 1) & 1);
    output_bit(pin_G0, (G >> 0) & 1);
}

void control_traffic_lights()
{
    if (secs == 0)
    {
        set_lights(0b001, 0b001, 0b001);
    }
    else if (secs >= 1 && secs <= 2)
    {
        set_lights(0b011, 0b000, 0b000);
    }
    else if (secs >= 2 && secs <= 8)
    {
        set_lights(0b100, 0b000, 0b000);
    }
    else if (secs >= 8 && secs <= 9)
    {
        set_lights(0b010, 0b000, 0b000);
    }
    else if (secs > 9)
    {
        set_lights(0b001, 0b000, 0b000);
    }

    if (secs >= 10 && secs <= 12)
    {
        set_lights(0b000, 0b011, 0b000);
    }
    else if (secs >= 12 && secs <= 18)
    {
        set_lights(0b000, 0b100, 0b000);
    }
    else if (secs >= 18 && secs <= 19)
    {
        set_lights(0b000, 0b010, 0b000);
    }
    else if (secs > 19)
    {
        set_lights(0b000, 0b001, 0b000);
    }

    if (secs >= 20 && secs <= 22)
    {
        set_lights(0b000, 0b000, 0b011);
    }
    else if (secs >= 22 && secs <= 28)
    {
        set_lights(0b000, 0b000, 0b100);
    }
    else if (secs >= 28 && secs <= 29)
    {
        set_lights(0b000, 0b000, 0b010);
    }
    else if (secs > 29)
    {
        set_lights(0b000, 0b000, 0b001);
		output_high(pin_h3);
		output_low(pin_h4);
	}
	if (secs < 29)
	{
		output_high(pin_h4); 
		output_low(pin_h3);
	}

}
void clock(void)
{
	if(onesec_flag)
		{
			onesec_flag=0;
			secs++; if (secs==41){secs=1;}
			secs_2++; if (secs_2==41){secs_2=1;}
			secs_3++; if (secs_3==41){secs_3=1;}
		}
}	


void main() {
	setup_timer_2(T2_DIV_BY_16,240,13);		//1.9 ms overflow, 25.0 ms interrupt
	enable_interrupts(INT_TIMER2);
	enable_interrupts(GLOBAL);

    while (TRUE) {
		clock();
        update_display(secs);
		update_display_2(secs_2);
		update_display_3(secs_3);
		control_traffic_lights();
	}
}
